From 2d01f7786d72811de3e69e88aca9e76031384a91 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 17 Mar 2012 19:23:53 +0100 Subject: [PATCH] css: Add selector change types This allows querying selectors for which changes would change their "matchingness". --- gtk/gtkcssselector.c | 109 ++++++++++++++++++++++++++++++++++-- gtk/gtkcssselectorprivate.h | 3 +- gtk/gtkcsstypes.c | 56 ++++++++++++++++++ gtk/gtkcsstypesprivate.h | 34 +++++++++++ 4 files changed, 196 insertions(+), 6 deletions(-) diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c index 4bac4b4f2b..76cb7b109b 100644 --- a/gtk/gtkcssselector.c +++ b/gtk/gtkcssselector.c @@ -29,10 +29,11 @@ typedef struct _GtkCssSelectorClass GtkCssSelectorClass; struct _GtkCssSelectorClass { const char *name; - void (* print) (const GtkCssSelector *selector, - GString *string); - gboolean (* match) (const GtkCssSelector *selector, - const GtkCssMatcher *matcher); + void (* print) (const GtkCssSelector *selector, + GString *string); + gboolean (* match) (const GtkCssSelector *selector, + const GtkCssMatcher *matcher); + GtkCssChange (* get_change) (const GtkCssSelector *selector); guint increase_id_specificity :1; guint increase_class_specificity :1; @@ -57,6 +58,15 @@ gtk_css_selector_match (const GtkCssSelector *selector, return selector->class->match (selector, matcher); } +static GtkCssChange +gtk_css_selector_get_change (const GtkCssSelector *selector) +{ + if (selector == NULL) + return 0; + + return selector->class->get_change (selector); +} + static const GtkCssSelector * gtk_css_selector_previous (const GtkCssSelector *selector) { @@ -91,10 +101,17 @@ gtk_css_selector_descendant_match (const GtkCssSelector *selector, return FALSE; } +static GtkCssChange +gtk_css_selector_descendant_get_change (const GtkCssSelector *selector) +{ + return _gtk_css_change_for_child (gtk_css_selector_get_change (gtk_css_selector_previous (selector))); +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = { "descendant", gtk_css_selector_descendant_print, gtk_css_selector_descendant_match, + gtk_css_selector_descendant_get_change, FALSE, FALSE, FALSE }; @@ -119,10 +136,17 @@ gtk_css_selector_child_match (const GtkCssSelector *selector, return gtk_css_selector_match (gtk_css_selector_previous (selector), &parent); } +static GtkCssChange +gtk_css_selector_child_get_change (const GtkCssSelector *selector) +{ + return _gtk_css_change_for_child (gtk_css_selector_get_change (gtk_css_selector_previous (selector))); +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = { "child", gtk_css_selector_child_print, gtk_css_selector_child_match, + gtk_css_selector_child_get_change, FALSE, FALSE, FALSE }; @@ -152,10 +176,17 @@ gtk_css_selector_sibling_match (const GtkCssSelector *selector, return FALSE; } +static GtkCssChange +gtk_css_selector_sibling_get_change (const GtkCssSelector *selector) +{ + return _gtk_css_change_for_sibling (gtk_css_selector_get_change (gtk_css_selector_previous (selector))); +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = { "sibling", gtk_css_selector_sibling_print, gtk_css_selector_sibling_match, + gtk_css_selector_sibling_get_change, FALSE, FALSE, FALSE }; @@ -180,10 +211,17 @@ gtk_css_selector_adjacent_match (const GtkCssSelector *selector, return gtk_css_selector_match (gtk_css_selector_previous (selector), &previous); } +static GtkCssChange +gtk_css_selector_adjacent_get_change (const GtkCssSelector *selector) +{ + return _gtk_css_change_for_sibling (gtk_css_selector_get_change (gtk_css_selector_previous (selector))); +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = { "adjacent", gtk_css_selector_adjacent_print, gtk_css_selector_adjacent_match, + gtk_css_selector_adjacent_get_change, FALSE, FALSE, FALSE }; @@ -213,10 +251,17 @@ gtk_css_selector_any_match (const GtkCssSelector *selector, return gtk_css_selector_match (previous, matcher); } +static GtkCssChange +gtk_css_selector_any_get_change (const GtkCssSelector *selector) +{ + return gtk_css_selector_get_change (gtk_css_selector_previous (selector)); +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_ANY = { "any", gtk_css_selector_any_print, gtk_css_selector_any_match, + gtk_css_selector_any_get_change, FALSE, FALSE, FALSE }; @@ -239,10 +284,17 @@ gtk_css_selector_name_match (const GtkCssSelector *selector, return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher); } +static GtkCssChange +gtk_css_selector_name_get_change (const GtkCssSelector *selector) +{ + return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_NAME; +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_NAME = { "name", gtk_css_selector_name_print, gtk_css_selector_name_match, + gtk_css_selector_name_get_change, FALSE, FALSE, TRUE }; @@ -272,10 +324,23 @@ gtk_css_selector_region_match (const GtkCssSelector *selector, return gtk_css_selector_match (previous, matcher); } +static GtkCssChange +gtk_css_selector_region_get_change (const GtkCssSelector *selector) +{ + GtkCssChange change; + + change = gtk_css_selector_get_change (gtk_css_selector_previous (selector)); + change |= GTK_CSS_CHANGE_REGION; + change |= _gtk_css_change_for_child (change); + + return change; +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_REGION = { "region", gtk_css_selector_region_print, gtk_css_selector_region_match, + gtk_css_selector_region_get_change, FALSE, FALSE, TRUE }; @@ -299,10 +364,17 @@ gtk_css_selector_class_match (const GtkCssSelector *selector, return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher); } +static GtkCssChange +gtk_css_selector_class_get_change (const GtkCssSelector *selector) +{ + return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_CLASS; +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_CLASS = { "class", gtk_css_selector_class_print, gtk_css_selector_class_match, + gtk_css_selector_class_get_change, FALSE, TRUE, FALSE }; @@ -326,10 +398,17 @@ gtk_css_selector_id_match (const GtkCssSelector *selector, return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher); } +static GtkCssChange +gtk_css_selector_id_get_change (const GtkCssSelector *selector) +{ + return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_ID; +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_ID = { "id", gtk_css_selector_id_print, gtk_css_selector_id_match, + gtk_css_selector_id_get_change, TRUE, FALSE, FALSE }; @@ -377,10 +456,17 @@ gtk_css_selector_pseudoclass_state_match (const GtkCssSelector *selector, return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher); } +static GtkCssChange +gtk_css_selector_pseudoclass_state_get_change (const GtkCssSelector *selector) +{ + return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_STATE; +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_STATE = { "pseudoclass-state", gtk_css_selector_pseudoclass_state_print, gtk_css_selector_pseudoclass_state_match, + gtk_css_selector_pseudoclass_state_get_change, FALSE, TRUE, FALSE }; @@ -487,10 +573,17 @@ gtk_css_selector_pseudoclass_region_match (const GtkCssSelector *selector, return gtk_css_selector_match (previous, matcher); } +static GtkCssChange +gtk_css_selector_pseudoclass_region_get_change (const GtkCssSelector *selector) +{ + return gtk_css_selector_get_change (gtk_css_selector_previous (selector)) | GTK_CSS_CHANGE_POSITION; +} + static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_REGION = { "pseudoclass-region", gtk_css_selector_pseudoclass_region_print, gtk_css_selector_pseudoclass_region_match, + gtk_css_selector_pseudoclass_region_get_change, FALSE, TRUE, FALSE }; @@ -815,6 +908,14 @@ _gtk_css_selector_to_string (const GtkCssSelector *selector) return g_string_free (string, FALSE); } +GtkCssChange +_gtk_css_selector_get_change (const GtkCssSelector *selector) +{ + g_return_val_if_fail (selector != NULL, 0); + + return gtk_css_selector_get_change (selector); +} + /** * _gtk_css_selector_matches: * @selector: the selector diff --git a/gtk/gtkcssselectorprivate.h b/gtk/gtkcssselectorprivate.h index e1d7623867..6430054e90 100644 --- a/gtk/gtkcssselectorprivate.h +++ b/gtk/gtkcssselectorprivate.h @@ -18,8 +18,6 @@ #ifndef __GTK_CSS_SELECTOR_PRIVATE_H__ #define __GTK_CSS_SELECTOR_PRIVATE_H__ -#include -#include #include "gtk/gtkcssmatcherprivate.h" #include "gtk/gtkcssparserprivate.h" @@ -36,6 +34,7 @@ void _gtk_css_selector_print (const GtkCssSelector *sel GtkStateFlags _gtk_css_selector_get_state_flags (const GtkCssSelector *selector); +GtkCssChange _gtk_css_selector_get_change (const GtkCssSelector *selector); gboolean _gtk_css_selector_matches (const GtkCssSelector *selector, const GtkCssMatcher *matcher); int _gtk_css_selector_compare (const GtkCssSelector *a, diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c index 508a3db72e..0133c723bb 100644 --- a/gtk/gtkcsstypes.c +++ b/gtk/gtkcsstypes.c @@ -36,6 +36,62 @@ DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderCornerRadius, _gtk_css_border_corn DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssBorderImageRepeat, _gtk_css_border_image_repeat) DEFINE_BOXED_TYPE_WITH_COPY_FUNC (GtkCssNumber, _gtk_css_number) +typedef struct _GtkCssChangeTranslation GtkCssChangeTranslation; +struct _GtkCssChangeTranslation { + GtkCssChange from; + GtkCssChange to; +}; + +static GtkCssChange +gtk_css_change_translate (GtkCssChange match, + const GtkCssChangeTranslation *translations, + guint n_translations) +{ + GtkCssChange result = match; + guint i; + + for (i = 0; i < n_translations; i++) + { + if (match & translations[i].from) + { + result &= ~translations[i].from; + result |= translations[i].to; + } + } + + return result; +} + +GtkCssChange +_gtk_css_change_for_sibling (GtkCssChange match) +{ + static const GtkCssChangeTranslation table[] = { + { GTK_CSS_CHANGE_CLASS, GTK_CSS_CHANGE_SIBLING_CLASS }, + { GTK_CSS_CHANGE_NAME, GTK_CSS_CHANGE_SIBLING_NAME }, + { GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_SIBLING_POSITION }, + { GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_SIBLING_STATE }, + }; + + return gtk_css_change_translate (match, table, G_N_ELEMENTS (table)); +} + +GtkCssChange +_gtk_css_change_for_child (GtkCssChange match) +{ + static const GtkCssChangeTranslation table[] = { + { GTK_CSS_CHANGE_CLASS, GTK_CSS_CHANGE_PARENT_CLASS }, + { GTK_CSS_CHANGE_NAME, GTK_CSS_CHANGE_PARENT_NAME }, + { GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_PARENT_POSITION }, + { GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_PARENT_STATE }, + { GTK_CSS_CHANGE_SIBLING_CLASS, GTK_CSS_CHANGE_PARENT_SIBLING_CLASS }, + { GTK_CSS_CHANGE_SIBLING_NAME, GTK_CSS_CHANGE_PARENT_SIBLING_NAME }, + { GTK_CSS_CHANGE_SIBLING_POSITION, GTK_CSS_CHANGE_PARENT_SIBLING_POSITION }, + { GTK_CSS_CHANGE_SIBLING_STATE, GTK_CSS_CHANGE_PARENT_SIBLING_STATE } + }; + + return gtk_css_change_translate (match, table, G_N_ELEMENTS (table)); +} + void _gtk_css_number_init (GtkCssNumber *number, double value, diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h index 7f239312df..c064b863eb 100644 --- a/gtk/gtkcsstypesprivate.h +++ b/gtk/gtkcsstypesprivate.h @@ -23,6 +23,37 @@ G_BEGIN_DECLS +typedef enum { /*< skip >*/ + GTK_CSS_CHANGE_CLASS = (1 << 0), + GTK_CSS_CHANGE_NAME = (1 << 1), + GTK_CSS_CHANGE_ID = GTK_CSS_CHANGE_NAME, + GTK_CSS_CHANGE_REGION = GTK_CSS_CHANGE_NAME, + GTK_CSS_CHANGE_POSITION = (1 << 2), + GTK_CSS_CHANGE_STATE = (1 << 3), + GTK_CSS_CHANGE_SIBLING_CLASS = (1 << 4), + GTK_CSS_CHANGE_SIBLING_NAME = (1 << 5), + GTK_CSS_CHANGE_SIBLING_POSITION = (1 << 6), + GTK_CSS_CHANGE_SIBLING_STATE = (1 << 7), + GTK_CSS_CHANGE_PARENT_CLASS = (1 << 8), + GTK_CSS_CHANGE_PARENT_NAME = (1 << 9), + GTK_CSS_CHANGE_PARENT_POSITION = (1 << 10), + GTK_CSS_CHANGE_PARENT_STATE = (1 << 11), + GTK_CSS_CHANGE_PARENT_SIBLING_CLASS = (1 << 12), + GTK_CSS_CHANGE_PARENT_SIBLING_NAME = (1 << 13), + GTK_CSS_CHANGE_PARENT_SIBLING_POSITION = (1 << 14), + GTK_CSS_CHANGE_PARENT_SIBLING_STATE = (1 << 15), + /* add more */ +} GtkCssChange; + +#define GTK_CSS_CHANGE_ANY ((1 << 16) - 1) +#define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_STATE) +#define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_SIBLING_CLASS | GTK_CSS_CHANGE_SIBLING_NAME | \ + GTK_CSS_CHANGE_SIBLING_POSITION | GTK_CSS_CHANGE_SIBLING_STATE) +#define GTK_CSS_CHANGE_ANY_PARENT (GTK_CSS_CHANGE_PARENT_CLASS | GTK_CSS_CHANGE_PARENT_SIBLING_CLASS | \ + GTK_CSS_CHANGE_PARENT_NAME | GTK_CSS_CHANGE_PARENT_SIBLING_NAME | \ + GTK_CSS_CHANGE_PARENT_POSITION | GTK_CSS_CHANGE_PARENT_SIBLING_POSITION | \ + GTK_CSS_CHANGE_PARENT_STATE | GTK_CSS_CHANGE_PARENT_SIBLING_STATE) + typedef enum { GTK_CSS_INHERIT, GTK_CSS_INITIAL @@ -142,6 +173,9 @@ GType _gtk_css_border_corner_radius_get_type (void); GType _gtk_css_border_image_repeat_get_type (void); GType _gtk_css_number_get_type (void); +GtkCssChange _gtk_css_change_for_sibling (GtkCssChange match); +GtkCssChange _gtk_css_change_for_child (GtkCssChange match); + #define GTK_CSS_NUMBER_INIT(_value,_unit) { (_value), (_unit) } void _gtk_css_number_init (GtkCssNumber *number, double value, -- 2.30.2